package com.cloudsea.yunhaianalysis.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.lang.Snowflake;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.cloudsea.yunhaianalysis.entity.Warnings;
import com.cloudsea.yunhaianalysis.mapper.WarningsMapper;
import com.cloudsea.yunhaianalysis.service.WarningService;
import com.cloudsea.yunhaistores.entity.MerchantUsers;
import com.cloudsea.yunhaistores.entity.Stores;
import com.cloudsea.yunhaistores.mapper.MerchantUsersMapper;
import com.cloudsea.yunhaistores.mapper.StoresMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class WarningServiceImpl implements WarningService {
    @Autowired
    private WarningsMapper warningsMapper;

    @Autowired
    private Snowflake snowflake;

    @Autowired
    private MerchantUsersMapper merchantUsersMapper;

    @Autowired
    private StoresMapper storesMapper;

    @Autowired
    private StringRedisTemplate redisTemplate;

    private static final String WARNING_LOCK_KEY_PREFIX = "warning:lock:";
    @Override
    public void createWarning(Long storeId, String type, String content) {
        // 【核心改造】预警前检查

        // 1. 构造用于冷却控制的Redis Key
        //    为了简化，我们只锁到门店和类型级别，避免对每个SKU都生成预警
        String lockKey = WARNING_LOCK_KEY_PREFIX + storeId + ":" + type + ":" + LocalDate.now().toString();

        // 2. 尝试在Redis中为这个Key设置一个值，只有在Key不存在时才能成功
        //    我们利用Redis的 setIfAbsent (SETNX) 操作的原子性
        Boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 12, TimeUnit.HOURS);

        // 3. 如果 locked 为 true，说明我们成功获得了“预警权”，可以继续
        if (Boolean.TRUE.equals(locked)) {
            Warnings warning = new Warnings();
            warning.setId(snowflake.nextId());
            warning.setStoreId(storeId);
            warning.setWarningType(type);
            warning.setContent(content);
            warning.setIsRead(false);
            warning.setCreatedAt(LocalDateTime.now());
            warningsMapper.insert(warning);
        }
        // 如果 locked 为 false，说明在12小时内已经为该门店的同类型事件发过预警，直接静默返回。
    }
    @Override
    public List<Warnings> getLatestUnreadWarnings(Long storeId) {
        // 在执行任何业务逻辑前，先进行权限校验
        this.checkStorePermission(storeId);

        return warningsMapper.selectList(new QueryWrapper<Warnings>()
                .eq("store_id", storeId)
                .eq("is_read", false)
                .orderByDesc("created_at"));
    }

    @Override
    public void markAsRead(Long warningId) {
        // 1. 查询预警信息
        Warnings warning = warningsMapper.selectById(warningId);
        if (warning == null) {
            // 如果预警不存在，直接返回，不做任何操作
            return;
        }

        // 2. 【安全校验】检查当前操作员是否有权操作此预警
        //    我们通过预警关联的storeId来进行校验
        this.checkStorePermission(warning.getStoreId());

        // 3. 更新 is_read 字段
        //    只有在未读的情况下才更新，避免不必要的数据库操作
        if (!warning.getIsRead()) {
            warning.setIsRead(true);
            warningsMapper.updateById(warning);
        }
    }

    @Override
    public void markAllAsRead(Long storeId) {
        // 1. 【安全校验】检查当前操作员是否有权操作此门店
        this.checkStorePermission(storeId);

        // 2. 创建一个批量更新的条件构造器
        UpdateWrapper<Warnings> updateWrapper = new UpdateWrapper<>();

        // 3. 设置更新条件 (WHERE)
        updateWrapper
                .eq("store_id", storeId) // 条件1: 属于该门店
                .eq("is_read", false); // 条件2: 并且是未读状态

        // 4. 设置要更新的字段 (SET)
        updateWrapper.set("is_read", true);

        // 5. 执行批量更新
        //    mapper.update(entity, wrapper) 中，当entity为null时，会直接使用wrapper的set语句
        warningsMapper.update(null, updateWrapper);
    }

    private void checkStorePermission(Long storeId) {
        if (storeId == null) {
            throw new IllegalArgumentException("门店ID不能为空");
        }

        long loginId = StpUtil.getLoginIdAsLong();
        MerchantUsers currentUser = merchantUsersMapper.selectById(loginId);
        if (currentUser == null || currentUser.getMerchantId() == null) {
            throw new SecurityException("无法获取当前用户信息，权限校验失败");
        }
        Long operatorMerchantId = currentUser.getMerchantId();

        Stores targetStore = storesMapper.selectById(storeId);
        if (targetStore == null) {
            throw new RuntimeException("操作的门店不存在");
        }
        Long targetMerchantId = targetStore.getMerchantId();

        if (!operatorMerchantId.equals(targetMerchantId)) {
            throw new SecurityException("权限不足，您只能为自己商户下的门店添加事件");
        }
    }
}
